﻿#include "handler.h"

Handler::Handler(QObject *parent) : QObject(parent)
{
    separator=",";
}

QString Handler::prepare(const QString &source)
{
    QString path{};
    QDir dir(source);
    if(dir.exists())
    {
        //必须使用绝对路径
        path=dir.path();
        if(dir.isRelative())
            if(dir.makeAbsolute())
                path=dir.path();
            else
                path=QString();
    }
    return path;
}

void Handler::read_config(const QString &filePath)
{
    QFile file(filePath);
    if(!file.exists())
    {
        qDebug() << "error: file not exists";
        return;
    }

    if(!file.open(QFile::ReadOnly | QFile::Text))
    {
        qDebug() << "error: file cannot open";
        return;
    }

    QJsonDocument doc=QJsonDocument::fromJson(file.readAll());
    QJsonObject obj=doc.object();
    if(obj.isEmpty())
    {
        qDebug() << "error: format incorrect";
        return;
    }

    QString source=obj.value("source").toString();
    if(source.isEmpty())
    {
        qDebug() << "error: source is empty";
        return;
    }
    QString destination=obj.value("destination").toString();
    if(destination.isEmpty())
        destination="out.txt";
    QString actionString=obj.value("action").toString();
    if(actionString.isEmpty())
    {
        qDebug() << "error: action is empty";
        return;
    }

    int action=ACT_NULL;
    if(actionString == "scan")
        action=ACT_SCAN;
    else if(actionString == "copy")
        action=ACT_COPY;
    else if(actionString == "move")
        action=ACT_MOVE;
    else if(actionString == "delete")
        action=ACT_DELETE;
    else if(actionString == "sha1")
        action=ACT_SHA1;

    if(action == ACT_SCAN)
        scanOption(obj);

    QStringList filter{};
    if(obj.contains("filter"))
    {
        QJsonArray array=obj.value("filter").toArray();
        if(array.isEmpty())
            filter=QStringList();
        else
        {
            for(int i=0;i < array.size();i++)
            {
                filter.append(array.at(i).toString());
            }
        }
    }

    operate(action,source,destination,filter);
}

void Handler::scanOption(const QJsonObject &obj)
{
    if(obj.contains("sep"))
    {
        separator=obj.value("sep").toString();
        if(separator.isEmpty())
            separator=",";
    }
}

void Handler::operate(int action,
                      const QString &source,
                      const QString &destination,
                      const QStringList &nameFilters)
{
    QString path=prepare(source);
    if(path.isEmpty())
    {
        qDebug() << "error: invalid path";
        return;
    }

    qDebug() << "Processing...";
    switch (action) {
    case ACT_NULL:
    {
        qDebug() << "error: invalid action";
        return;
    }
        break;
    case ACT_SCAN:
        scan(path,destination,nameFilters);
        break;
    case ACT_COPY:
        copy(path,destination,nameFilters);
        break;
    case ACT_MOVE:
        move(path,destination,nameFilters);
        break;
    case ACT_DELETE:
        remove(path,nameFilters);
        break;
    case ACT_SHA1:
        break;
    }
    qDebug() << "Finished";
}

void Handler::scan(const QString &source,
                   const QString &destination,
                   const QStringList &nameFilters)
{
    qDebug() << "Current Operation : Scan";

    QFile file(destination);
    if(!file.open(QFile::WriteOnly | QFile::Text))
    {
        qDebug() << "error: file cannot open";
        return;
    }
    QTextStream stream(&file);
    stream.setCodec("UTF-8");

    QDirIterator dirIter(source,nameFilters,QDir::Files,
                         QDirIterator::Subdirectories);
    while (dirIter.hasNext()) {
        dirIter.next(); //缺少会成为死循环！
        stream << dirIter.fileName() << separator
               << dirIter.filePath() << "\n";
    }
    stream.flush();
    file.close();
}

void Handler::copy(const QString &source, const QString &destination,
                   const QStringList &nameFilters)
{
    qDebug() << "Current Operation : Copy";
    QDir dir(destination);
    if(dir.isRelative())
        if(!dir.makeAbsolute())
        {
            qDebug() << "error: invalid path";
            return;
        }

    QString targetDir=dir.path();
    if(!dir.exists())
        dir.mkpath(targetDir);

    QDirIterator dirIter(source,nameFilters,QDir::Files,
                         QDirIterator::Subdirectories);
    while (dirIter.hasNext()) {
        dirIter.next();
        QString sourcePath=dirIter.filePath();
        QString target=targetDir + "/" + dirIter.fileName();
        if(!QFile::copy(dirIter.filePath(),target))
            qDebug() << "error: cannot copy" << sourcePath;
    }
}

void Handler::move(const QString &source, const QString &destination,
                   const QStringList &nameFilters)
{
    qDebug() << "Current Operation : Move";
    QDir dir(destination);
    if(dir.isRelative())
        if(!dir.makeAbsolute())
        {
            qDebug() << "error: invalid path";
            return;
        }

    QString targetDir=dir.path();
    if(!dir.exists())
        dir.mkpath(targetDir);

    QDirIterator dirIter(source,nameFilters,QDir::Files,
                         QDirIterator::Subdirectories);
    while (dirIter.hasNext()) {
        dirIter.next();
        QString sourcePath=dirIter.filePath();
        QString target=targetDir + "/" + dirIter.fileName();
        if(!QFile::rename(sourcePath,target))
            qDebug() << "error: cannot move" << sourcePath;
    }
}

void Handler::remove(const QString &source, const QStringList &nameFilters)
{
    qDebug() << "Current Operation : Remove";
    QDirIterator dirIter(source,nameFilters,QDir::Files,
                         QDirIterator::Subdirectories);
    while (dirIter.hasNext()) {
        dirIter.next();
        QString sourcePath=dirIter.filePath();
        if(!QFile::remove(sourcePath))
            qDebug() << "error: cannot delete" << sourcePath;
    }
}

void Handler::verify_sha1(const QString &source, const QString &destination, const QStringList &nameFilters)
{
    qDebug() << "Current Operation : SHA1 Verify";
}


